#!/usr/bin/env node
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const fs = require('fs');
const checker = require('license-checker');

const LICENSES_FILE = '../licenses.yaml';
const START_MARKER_LINE = '# Web console modules start';
const END_MARKER_LINE = '# Web console modules end';
const SEPARATOR = '\n\n---\n\n';

function injectConsoleLicenses(consoleLicenses) {
  const text = fs.readFileSync(LICENSES_FILE, 'utf-8');
  const textLines = text.split('\n');

  // Extract the license for the file itself
  let beforeLines = [];
  let afterLines = [];
  let state = 'before';
  for (let textLine of textLines) {
    switch (state) {
      case 'before':
        beforeLines.push(textLine);
        if (textLine === START_MARKER_LINE) {
          state = 'main';
        }
        break;

      case 'main':
        if (textLine === END_MARKER_LINE) {
          state = 'after';
          afterLines.push(textLine);
        }
        break;

      case 'after':
        afterLines.push(textLine);
        break;
    }
  }
  if (state === 'before') throw new Error(`missing starter marker '${START_MARKER_LINE}'`);
  if (state === 'main') throw new Error(`missing ending marker '${END_MARKER_LINE}'`);

  // Write out the new file
  fs.writeFileSync(
    LICENSES_FILE,
    [
      beforeLines.join('\n'),
      consoleLicenses.join(SEPARATOR),
      afterLines.join('\n')
    ].join('\n')
  );
}

checker.init({
  start: '.',
  production: true
}, function(err, packages) {
  if (err) {
    console.log('err', err);
    return;
  }

  const mapped = Object.keys(packages).sort().map(p => {
    const m = p.match(/^(.+)@(\d+\.\d+\.\d+.*)$/);
    if (!m) throw new Error(`Malformed name@version`);
    const name = m[1];
    if (name === 'web-console') return null; // This is me!

    const version = m[2];
    const meta = packages[p];
    let { publisher, licenses, licenseFile } = meta;
    if (!licenses) throw new Error(`Package '${p} does not have a licenses`);

    let properLicenseName; // Map the licenses to their proper name
    let licenseExt; // Map the licenses to the right extension
    switch (licenses) {
      case 'MIT':
        properLicenseName = 'MIT License';
        licenseExt = 'MIT';
        break;

      case 'Apache-2.0':
        properLicenseName = 'Apache License version 2.0';
        licenseExt = 'A2';
        break;

      case 'BSD-3-Clause':
        properLicenseName = 'BSD-3-Clause License';
        licenseExt = 'BSD3';
        break;

      default:
        throw new Error(`Unknown license '${licenses}' in ${p}`);
    }

    const simpleName = name.replace('/', '-');
    const licenseDest = `licenses/bin/${simpleName}.${licenseExt}`

    let hasLicense = false;
    if (licenseExt !== 'A2') {
      if (licenseFile && licenseFile.match(/\/license(?:\.\w+)?/i)) {
        // If the file ends with license.ext? then copy it over
        try {
          fs.copyFileSync(licenseFile, `../${licenseDest}`);
          hasLicense = true;
        } catch (e) {
          console.log(`Could not copy license for '${p}': ${JSON.stringify(meta)}`);
        }
      } else {
        // See if the license is already there (manually) keep it
        try {
          fs.statSync(`../${licenseDest}`);
          hasLicense = true;
        } catch (e) {
          console.log(`Could not find license for '${p}': ${JSON.stringify(meta)}`);
        }
      }
    }

    if (!publisher && hasLicense) {
      // Extract copyright from license
      const licenseText = fs.readFileSync(`../${licenseDest}`, 'utf-8');
      const m = licenseText.match(/(?:^|\n)\s*Copyright(?: (?:\(c\)|©))?(?: 2[0-9]{3}(?:-\w+)?,?)? ([^0-9][^\n]*)\n/m);
      if (m) {
        publisher = m[1]
          .replace(/All rights reserved./i, '')
          .replace(/[0-9-]{4,9}/, '')
          .trim();
      }
    }

    if (!publisher) {
      // Hand coded copyrights
      if (name === 'asap') publisher = 'Contributors'
      if (name === 'diff-match-patch') publisher = 'Google'
    }

    if (!publisher) {
      console.log(`No license for '${name}' ('${licenseDest}')`);
    }

    // Make our blob
    const lines = [
      `name: "${name}"`,
      `license_category: binary`,
      `module: web-console`,
      `license_name: ${properLicenseName}`,
      publisher ? `copyright: ${publisher}` : null,
      `version: ${version}`,
      hasLicense ? `license_file_path: ${licenseDest}` : null,
    ];

    return lines.filter(Boolean).join('\n');
  }).filter(Boolean);

  injectConsoleLicenses(mapped);
});

